
#include <string>
#include <sstream>
#include <iomanip>
#include "netcdfRead.hpp"


netcdf_is_complex_float::netcdf_is_complex_float(const char* filename, const char* channelname)
:
mFilename(filename),mChannelname(channelname)
{
    mCheckpointCount = 0;
    mFile = 0;
    mChannelnameRe = mChannelname + std::string(".re");
    mChannelnameIm = mChannelname + std::string(".im");
    mRealData = 0;
    mImaginaryData = 0;
    mTimeVar = 0;
    mDt = 0.0;
    mStartTime = 0.0;
    OpenFile();
    GetRecord();
}

netcdf_is_complex_float::~netcdf_is_complex_float()
{
    if( mFile != 0) delete mFile;
}

void netcdf_is_complex_float::read(cvectorf* data)
{
    for(int i=0;i<data->size();i++) {
        if(mDataRead==mRecordSize) GetRecord();
        data->set(i,mRealData[mDataRead],mImaginaryData[mDataRead]);
        mDataRead++;
    }
}

void netcdf_is_complex_float::read(vectorf* redata, vectorf* imdata)
{
    if( redata->size() != imdata->size()) {
        std::cerr << "size of input vectors are different" << std::endl;
        throw;
    }
    for(int i=0;i<redata->size();i++) {
        if(mDataRead==mRecordSize) GetRecord();
        redata->set(i,mRealData[mDataRead]);
        imdata->set(i,mImaginaryData[mDataRead]);
        mDataRead++;
    }
}


void netcdf_is_complex_float::read(cvectorf* data, vector* times)
{
    for(int i=0;i<data->size();i++) {
        if(mDataRead==mRecordSize) GetRecord();
        data->set(i,mRealData[mDataRead],mImaginaryData[mDataRead]);
        times->set(i,mStartTime+mDataRead*mDt);
        mDataRead++;
    }   
}

void netcdf_is_complex_float::read(vectorf* redata, vectorf* imdata, vector* times)
{    
    if( redata->size() != imdata->size()) {
        std::cerr << "size of input vectors are different" << std::endl;
        throw;
    }
    for(int i=0;i<redata->size();i++) {
        if(mDataRead==mRecordSize) GetRecord();
        redata->set(i,mRealData[mDataRead]);
        imdata->set(i,mImaginaryData[mDataRead]);
        times->set(i,mStartTime+mDataRead*mDt);
        mDataRead++;
    }   
}

void netcdf_is_complex_float::read(cvector* data)
{
    for(int i=0;i<data->size();i++) {
        if(mDataRead==mRecordSize) GetRecord();
        data->set(i,mRealData[mDataRead],mImaginaryData[mDataRead]);
        mDataRead++;
    }
}

void netcdf_is_complex_float::read(vector* redata, vector* imdata)
{
    if( redata->size() != imdata->size()) {
        std::cerr << "size of input vectors are different" << std::endl;
        throw;
    }
    for(int i=0;i<redata->size();i++) {
        if(mDataRead==mRecordSize) GetRecord();
        redata->set(i,mRealData[mDataRead]);
        imdata->set(i,mImaginaryData[mDataRead]);
        mDataRead++;
    }
}


void netcdf_is_complex_float::read(cvector* data, vector* times)
{
    for(int i=0;i<data->size();i++) {
        if(mDataRead==mRecordSize) GetRecord();
        data->set(i,mRealData[mDataRead],mImaginaryData[mDataRead]);
        times->set(i,mStartTime+mDataRead*mDt);
        mDataRead++;
    }   
}

void netcdf_is_complex_float::read(vector* redata, vector* imdata, vector* times)
{    
    if( redata->size() != imdata->size()) {
        std::cerr << "size of input vectors are different" << std::endl;
        throw;
    }
    for(int i=0;i<redata->size();i++) {
        if(mDataRead==mRecordSize) GetRecord();
        redata->set(i,mRealData[mDataRead]);
        imdata->set(i,mImaginaryData[mDataRead]);
        times->set(i,mStartTime+mDataRead*mDt);
        mDataRead++;
    }   
}


void netcdf_is_complex_float::GetRecord()
{     
    if(mRecordRead==mRecords) {
        mCheckpointCount++;
        OpenFile();
    }
    mRealVar->set_cur(mRecordRead,0);
    mRealVar->get(mRealData,1,mRecordSize);
    mImaginaryVar->set_cur(mRecordRead,0);
    mImaginaryVar->get(mImaginaryData,1,mRecordSize);
    mTimeVar->set_cur(mRecordRead);
    mTimeVar->get(&mStartTime,1);
    mDataRead = 0;
    mRecordRead++;
    
}

void netcdf_is_complex_float::OpenFile()
{
    std::ostringstream fname;
    fname << mFilename << std::setfill('0') << std::setw(6) << mCheckpointCount << ".ncdf";  
    if(mFile!=0) {
        delete mFile;
        mFile = 0;
    }
    mFile = new NcFile(fname.str().c_str(),NcFile::ReadOnly,NULL,0,NcFile::Offset64Bits);   
    if(mFile->is_valid()) {
        std::cerr << "NEW FILE " << fname.str() << " OPENED" << std::endl;
    } else {
        std::cerr << "Cannot open " << fname  << std::endl;
        throw;
    }
    mRealVar = mFile->get_var(mChannelnameRe.c_str());
    mImaginaryVar = mFile->get_var(mChannelnameIm.c_str());
    mTimeVar = mFile->get_var("time");
    mRecords = mFile->get_dim("time")->size();
    mRecordSize = mFile->get_dim("t")->size();
    mRecordRead = 0;
    if(mRealData!=0) delete[] mRealData;
    if(mImaginaryData!=0) delete[] mImaginaryData; 
    mRealData = new float[mRecordSize];
    mImaginaryData = new float[mRecordSize];  
    NcAtt* att_sampling = mRealVar->get_att("sampling_rate");
    if(att_sampling==0) {
        std::cerr << "No sampling time attribute found." << std::cerr;
        throw;
    }
    mDt = att_sampling->as_double(0);
    delete att_sampling;
}